#ifndef DEFENSE_HPP
#define DEFENSE_HPP

#include "iarmy.hpp"

// захват муровейников
class defense
  : public iarmy
{
  igeneral* _g;
  wavemap _wavemap;
  bitmap _not_available;
  std::map<location, wavemap> _myhills;
  std::set<location> _myhills_locations;
  std::ofstream f; 
public:
  defense():_g(0) { f.open("defense.txt");}

  virtual void reconnaissance( igeneral* g)
  {
    
    std::cerr << "defense 1" << std::endl;
    if ( _g == 0 )
    {
      _g = g;
      _wavemap.create( _g->area(), &_not_available );
    }
    f << "TURN "<< _g->turn() << std::endl; 
    _not_available = g->istudy();
    _not_available |= g->water();
    double viewradius = _g->viewradius();
    if ( _g->turn() % 50 == 0  )
      _wavemap.reset();
    
    std::cerr << "defense 2" << std::endl;
    /// TODO: сделать сбос карты при изменении области исследования на 10% или каждые 50 ходов
    // сбрасываем значения в области видимости
    {{ 
      
    //_myhills&= _g->ivisible();
    /// Устанавливаем заного в области видимости
    const std::vector<item>& hilllist = _g->hilllist();
    std::vector<item>::const_iterator beg = hilllist.begin();
    std::vector<item>::const_iterator end = hilllist.end();
    for ( ;beg!=end; ++beg)
    {
      // Если враг то продолжаем
      if ( beg->value != 0 )
        continue;
      
      wavemap& hill = _myhills[*beg];
      if ( !hill )
      {
        f << "BEGIN DRIVE " << std::endl;
        hill.create(_g->area(), &_not_available);
        hill.set(*beg);
        if ( hill )
          f  << "READY???? 1" << std::endl;
        hill.begin_drive();
        if ( hill )
          f  << "READY???? 2" << std::endl;
      }
      int i=0;
      for (; i < viewradius*3 && !hill; ++i)
      {
          f << "DRIVE WAVE " << i << std::endl;
          hill.drive_wave();
      }
      if (i >  0 )
        hill.show(f, "MY HILL");
      
      /*
      _myhills.set(*beg);
      //_wavemap.set(*beg);
      // То что в списке потеряные муровейники не особо волнует, проще проверку сделать
      _myhills_locations.insert(*beg);
      */
    }
    /*
    _wavemap.set( _myhills );
    if ( !_wavemap )
    {
        _wavemap.begin_drive();
        for (int i=0; i < viewradius*3 && !_wavemap; ++i)
          _wavemap.drive_wave();
        _wavemap.show(f, "hill wavemap");
    }*/
    
    }}

    std::cerr << "defense 3" << std::endl;
    wavemap attackwave;
    attackwave.create( _g->area(), &_not_available);
    // Для каждого муровейника
    std::vector<advice>& forces = _g->forces();
    std::vector<item> enemyraiders = _g->enemyantlist();
    std::vector<item> mydefender = _g->myantlist();
    enemyraiders.reserve(100);
    mydefender.reserve(100);
    const bitmap& enemytroops = _g->enemyants();
    const bitmap& mytroops = _g->myants();
    
    //_wavemap.show(f, "hill wavemap");
    //enemytroops.show(f, "enemytroops");
    //mytroops.show(f, "mytroops");
    
    
    std::map<location, wavemap>::iterator beg = _myhills.begin();
    std::map<location, wavemap>::iterator end = _myhills.end();
    
    for ( ;beg!=end;++beg)
    {
      std::vector<item>::iterator ebeg = enemyraiders.begin();
      std::vector<item>::iterator eend = enemyraiders.end();
      for ( ;ebeg!=eend; ++ebeg)
        ebeg->value = beg->second.get(*ebeg);
      if ( !enemyraiders.empty() )
        std::sort(enemyraiders.begin(), enemyraiders.end(), weight_less() );
      
      std::vector<item>::iterator mbeg = mydefender.begin();
      std::vector<item>::iterator mend = mydefender.end();
      for ( ;mbeg!=mend; ++mbeg)
        mbeg->value = beg->second.get(*mbeg);
      if ( !mydefender.empty() )
        std::sort(mydefender.begin(), mydefender.end() , weight_less() );
      
      ebeg = enemyraiders.begin();
      eend = enemyraiders.end();
      mbeg = mydefender.begin();
      mend = mydefender.end();
      for ( ;ebeg!=eend; ++ebeg)
      {
        f << "ebeg->value="<<ebeg->value<<"<="<<viewradius<< "(" <<ebeg->row << ","<<ebeg->col <<")" <<std::endl;
        if ( ebeg->value > viewradius )
          continue;
        std::cerr << "defense 3.1.1" << std::endl;
        attackwave.reset();
        attackwave.set(*ebeg, 1, 20);
        beg->second.show(f, "attack wavemap");
        for ( int i = 0;mbeg!=mend && i < 3; ++mbeg, ++i)
        {
          if ( mbeg->value > viewradius*2 )
            break;
          int d = attackwave.direction(*mbeg);
          std::vector<advice>::iterator itr = std::lower_bound(forces.begin(), forces.end(), *mbeg);
          if ( itr != forces.end())
          {
            itr->direction = d;
            std::cerr << "defense 3.1.1 direction " << d<< std::endl;
          }
        }
      }

      /*
      f << "NEXT HILL "<< std::endl; 
      std::cerr << "defense 3.1" << std::endl;
      // Получаем всех врагов которые ближе чем viewradius*3
      enemyraiders.clear();
      mydefender.clear();
      _wavemap.nears( *beg, 1, enemytroops, viewradius*3, enemyraiders  );
      std::cerr << "defense 3.1-" << std::endl;
      continue;
      // Никого - нет забиваем
      // TODO: оставить хотябы 10% неподалеку 
      if (enemyraiders.empty())
        continue;
      
      std::sort(enemyraiders.begin(), enemyraiders.end());

      _wavemap.nears( *beg, 1, mytroops, viewradius*3, mydefender );

      // Никого - нет забиваем
      // TODO: это пиздец - наверное забиваем, нашу армию разбили
      if (mydefender.empty())
        continue;
      
      std::sort(mydefender.begin(), mydefender.end());
      
      int enemy_ring0 = 0;  // viewradius/2
      int enemy_ring1 = 0;  // viewradius
      int enemy_ring2 = 0;  // viewradius*2
      int enemy_ring3 = 0;  // viewradius*3
      
      std::vector<item>::iterator ebeg = enemyraiders.begin();
      std::vector<item>::iterator eend = enemyraiders.end();
      std::vector<item>::iterator mbeg = mydefender.begin();
      std::vector<item>::iterator mend = mydefender.end();
      for ( ;ebeg!=eend; ++ebeg)
      {
        std::cerr << "defense 3.1.1" << std::endl;
        attackwave.reset();
        attackwave.set(*ebeg, 1, viewradius*2);
        _wavemap.show(f, "attack wavemap");
        for ( int i = 0;mbeg!=mend && i < 3; ++mbeg, ++i)
        {
          int d = attackwave.direction(*mbeg);
          std::vector<advice>::iterator itr = std::lower_bound(forces.begin(), forces.end(), *mbeg);
          if ( itr != forces.end())
          {
            itr->direction = d;
            std::cerr << "defense 3.1.1 direction " << d<< std::endl;
          }
        }
        if ( ebeg->weight <= viewradius/2 )
          ++enemy_ring0;
        else if ( ebeg->weight <= viewradius)
          ++enemy_ring1;
        else if ( ebeg->weight <= viewradius*2)
          ++enemy_ring2;
        else if ( ebeg->weight <= viewradius*2)
          ++enemy_ring3;
          
        
      }*/
      
    }
    
    
    
    //std::vector<item>& nrs
/*
        if ( _g == 0 )
    {
      _g = g;
    }
    bitmap visible = _g->visible();
    visible.inverse();
    // сбрасываем значения в области видимости
    _ememyhills&= visible;

    const std::vector<item>& hilllist = _g->hilllist();

    std::vector<item>::const_iterator beg = hilllist.begin();
    std::vector<item>::const_iterator end = hilllist.end();
    for ( ;beg!=end; ++beg)
      _ememyhills.set(*beg);
    */
    

  }
private:

};

#endif